
package com.studiofortress.sf.util;

/**
 * All times in this Timer object are in milliseconds. The timer starts from the
 * moment of it's creation.
 *
 * @author Joseph Lenton
 */
public class Timer
{
    private final long startTime;
    private final long endTime;
    private final long duration;

    /**
     * @param duration The amount of time, in milliseconds, that this timer will last for.
     */
    public Timer(long duration, double percentDone)
    {
        if (duration <= 0) {
            throw new IllegalArgumentException("The duration cannot be less or equal to 0, given: " + duration);
        } else if ( percentDone < 0 ) {
            throw new IllegalArgumentException("The percentDone cannot be less or equal to 0, given: " + percentDone);
        }
        
        this.duration = duration;
        this.startTime = System.currentTimeMillis() - Math.round(duration*percentDone);
        this.endTime = startTime + duration;
    }

    /**
     * @param duration The amount of time, in milliseconds, that this timer will last for.
     */
    public Timer(long duration)
    {
        if (duration <= 0) {
            throw new IllegalArgumentException("The duration cannot be less or equal to 0, given: " + duration);
        }
        
        this.duration = duration;
        this.startTime = System.currentTimeMillis();
        this.endTime = startTime + duration;
    }

    /**
     * An inverse timer is a timer with the same duration as this timer, but
     * where the percentage that is complete is 1.0 - the current amount of
     * duration done. So if this timer has completed 0.3 of it's duration so far,
     * then the inverse timer will have completed 0.7 so far.
     *
     * This method is to help with timer based algorithms (like a fade) where
     * you want to reverse the algorithm half way through.
     *
     * @return A new Timer which has it's percentage complete as the inverse of this one.
     */
    public Timer getInverse()
    {
       return new Timer( duration, 1.0-getPercentDuration() ) ;
    }

    /**
     * @return The time that this Timer was created.
     */
    public long getStartTime()
    {
        return startTime;
    }

    /**
     * @return The time that this Timer was created, plus it's duration.
     */
    public long getEndTime()
    {
        return endTime;
    }

    /**
     * @return True if this Timer is now past it's end time.
     */
    public boolean isPastDuration()
    {
        return System.currentTimeMillis() > getEndTime();
    }

    /**
     * @return The amount of time between the start and end time of this Timer.
     */
    public long getDuration()
    {
        return duration;
    }

    /**
     * The percent duration is based on this moment, now, when it is called.
     * @return A value from 0 to 1 describing how much of the duration this timer has gone through.
     */
    public float getPercentDuration()
    {
        final float percent = (float)(System.currentTimeMillis()-startTime) / (float)duration;
        return Math.min( Math.max(0.0f, percent), 1.0f );
    }
}
